package com.atguigu.spzx.cart.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.spzx.cart.service.CartService;
import com.atguigu.spzx.common.exception.GuiguException;
import com.atguigu.spzx.common.interceptor.SpzxUserInfoInterceptor;
import com.atguigu.spzx.model.entity.cart.CartInfo;
import com.atguigu.spzx.model.entity.product.ProductSku;
import com.atguigu.spzx.model.entity.user.UserInfo;
import com.atguigu.spzx.model.vo.common.Result;
import com.atguigu.spzx.model.vo.common.ResultCodeEnum;
import com.atguigu.spzx.product.client.ProductClient;
import jakarta.annotation.Resource;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {
    @Resource
    ProductClient productClient;
    //stringRedisTemplate: 简单数据使用方便，复杂数据需要我们手动json处理
    @Resource
    StringRedisTemplate stringRedisTemplate;

    @Override
    public void addToCart(Long skuId, Integer count) {
        UserInfo userInfo = SpzxUserInfoInterceptor.THREAD_LOCAL.get();
        //1、查询用户的购物车
        String cartKey = "cart:user:" + userInfo.getId();
        //购物车hash结构存储 skuId -> CartInfo
        BoundHashOperations<String, String, String> hashOps =
                stringRedisTemplate.boundHashOps(cartKey);
        //2、判断是否存在skuId的购物项
        String cartInfoJson = hashOps.get(String.valueOf(skuId));
        CartInfo cartInfo = null;
        if (StringUtils.isEmpty(cartInfoJson)) {
            //不存在 新创建购物项保存
            cartInfo = new CartInfo();
            //查询sku对应的商品数据
            ProductSku productSku = productClient.findSkuBySkuId(skuId).getData();
            cartInfo.setCartPrice(productSku.getSalePrice());
            cartInfo.setImgUrl(productSku.getThumbImg());
            cartInfo.setIsChecked(1); //默认选中
            cartInfo.setSkuId(skuId);
            cartInfo.setSkuName(productSku.getSkuName());
            cartInfo.setSkuNum(count.longValue());
            cartInfo.setUserId(userInfo.getId());
            cartInfo.setCreateTime(new Date());
        } else {
            //存在  数量+count
            cartInfo = JSON.parseObject(cartInfoJson, CartInfo.class);
            cartInfo.setSkuNum(cartInfo.getSkuNum() + count);
        }
        cartInfo.setUpdateTime(new Date());
        //新增或者更新
        hashOps.put(String.valueOf(skuId), JSON.toJSONString(cartInfo));


        //    新建购物项
        //   在product中创建接口：根据skuId查询商品信息
        //Result不指定泛型： openfeign会将返回的json转为 LinkedHashMap


    }

    @Override
    public List<CartInfo> cartList() {
        // Map<skuId,cartInfoJsonStr>
        //1、根据userId获取他的购物车
        BoundHashOperations<String, String, String> hashOps = getRedisCart();
        if(hashOps.size()==0){
            return null;
        }
        //2、获取hash中的value值集合  转为CartInfo的集合返回
        List<CartInfo> cartInfoList = hashOps.values().stream()
                .map(str -> JSON.parseObject(str, CartInfo.class))
                .collect(Collectors.toList());
        return cartInfoList;
    }



    @Override
    public void checkCart(Long skuId, Integer status) {
        BoundHashOperations<String, String, String> cart = getRedisCart();
        String cartInfoJson = cart.get(skuId.toString());
        if(StringUtils.isEmpty(cartInfoJson)){
            throw new GuiguException(ResultCodeEnum.UNKNOW_ERROR);
        }
        CartInfo cartInfo = JSON.parseObject(cartInfoJson, CartInfo.class);
        //更新选中状态
        cartInfo.setIsChecked(status);
        //设置到redis中
        cart.put(skuId.toString() , JSON.toJSONString(cartInfo));
    }

    @Override
    public void allCheckCart(Integer status) {
        BoundHashOperations<String, String, String> cart = getRedisCart();

        //遍历所有的entry，将value值cartInfo选中状态改为status 然后put到hash中
        if(cart.size()==0){
            return;
        }
        cart.entries().forEach((skuId,cartInfoJson)->{
            CartInfo cartInfo = JSON.parseObject(cartInfoJson, CartInfo.class);
            cartInfo.setIsChecked(status);
            cart.put(skuId , JSON.toJSONString(cartInfo));
        });
    }

    @Override
    public void deleteCartInfo(Long skuId) {
        BoundHashOperations<String, String, String> cart = getRedisCart();
        cart.delete(String.valueOf(skuId));
    }

    @Override
    public void clearCart() {
        BoundHashOperations<String, String, String> cart = getRedisCart();
        cart.delete(cart.keys().toArray());
    }
    //查询会员的所有的选中的购物项集合
    @Override
    public List<CartInfo> getAllCheckedCartInfo() {
        // Map<skuId,cartInfoJsonStr>
        //1、根据userId获取他的购物车
        BoundHashOperations<String, String, String> hashOps = getRedisCart();
        if(hashOps.size()==0){
            return null;
        }
        //2、获取hash中的value值集合  转为CartInfo的集合返回
        List<CartInfo> cartInfoList = hashOps.values().stream()
                .map(str -> JSON.parseObject(str, CartInfo.class))
                .filter(cartInfo -> cartInfo.getIsChecked().equals(1))
                .collect(Collectors.toList());
        return cartInfoList;
    }

    @Override
    public void deleteCheckedCartInfo() {
        //1、获取用户的购物车
        BoundHashOperations<String, String, String> cart = getRedisCart();
        //2、删除购物车中选中的购物项
        cart.entries().forEach((skuIdStr ,  cartInfoStr)->{
            //判断正在遍历的购物项是否被选中
            CartInfo cartInfo = JSON.parseObject(cartInfoStr, CartInfo.class);
            if(cartInfo.getIsChecked().intValue()==1){
                //删除选中的购物项
                cart.delete(skuIdStr);
            }
        });
    }


    @NotNull
    private BoundHashOperations<String, String, String> getRedisCart() {
        UserInfo userInfo = SpzxUserInfoInterceptor.THREAD_LOCAL.get();
        String cartKey = "cart:user:" + userInfo.getId();
        BoundHashOperations<String, String, String> hashOps =
                stringRedisTemplate.boundHashOps(cartKey);
        return hashOps;
    }
}
